﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Go;
using GoRpc;

namespace GoRpcTest
{
    class Program
    {
        static async Task<int> add(int a, int b)
        {
            Console.WriteLine("rpc add {0}+{1}", a, b);
            await generator.sleep(100);
            return a + b;
        }

        static async Task<int> sub(int a, int b)
        {
            Console.WriteLine("                              rpc sub {0}-{1}", a, b);
            await generator.sleep(100);
            return a - b;
        }

        static async Task call_add(go_rpc.client rpcCli)
        {
            try
            {
                for (int i = 0; ; i++)
                {
                    Console.WriteLine("rpc add result {0}", await rpcCli.call<int>("add", 1000, i));
                    await generator.sleep(1000);
                }
            }
            catch (System.Exception) { }
            Console.WriteLine("call add error");
        }

        static async Task call_sub(go_rpc.client rpcCli)
        {
            try
            {
                await generator.sleep(50);
                for (int i = 0; ; i++)
                {
                    Console.WriteLine("                              rpc sub result {0}", await rpcCli.call<int>("sub", 1000, i));
                    await generator.sleep(1000);
                }
            }
            catch (System.Exception) { }
            Console.WriteLine("                              call sub error");
        }

        class remote_obj
        {
            int value1 = 0;
            int value2 = 0;

            async Task<int> add()
            {
                await generator.sleep(1000);
                return value1 + value2;
            }

            async Task<int> sub()
            {
                await generator.sleep(1000);
                return value1 - value2;
            }
        }

        static void Main(string[] args)
        {
            work_service work = new work_service();
            work_strand strand = new work_strand(work);
            go_rpc.server rpcSrv = new go_rpc.server(strand);
            rpcSrv.bind("add", (int a, int b) => add(a, b));
            rpcSrv.bind("sub", (int a, int b) => sub(a, b));
            rpcSrv.bind_obj("remote", new remote_obj());
            rpcSrv.bind("close", delegate ()
            {
                Console.WriteLine("close rpc server");
                rpcSrv.close();
            });
            rpcSrv.run("127.0.0.1", 2001);

            generator.go(strand, async delegate ()
            {
                go_rpc.client rpcCli = new go_rpc.client();
                if (await rpcCli.connect("127.0.0.1", 2001))
                {
                    generator.children children = new generator.children();
                    children.go(functional.bind(call_add, rpcCli));
                    children.go(functional.bind(call_sub, rpcCli));
                    await generator.sleep(10000);
                    await rpcCli.call("remote.set@value1", 456);
                    await rpcCli.call("remote.set@value2", 123);
                    Console.WriteLine("remote.add {0}", await rpcCli.call("remote.add"));
                    Console.WriteLine("remote.sub {0}", await rpcCli.call("remote.sub"));
                    try
                    {
                        await rpcCli.call("close");
                    }
                    catch (System.Exception) { }
                    await children.wait_all();
                }
                rpcCli.close();
            });
            work.run();
            Console.WriteLine("work done");
            Console.ReadKey();
        }
    }
}
